package com.itheima.datastructure.stack;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.function.Consumer;

/**
 * 特殊名单表达式校验+计算
 */
public class SpecialCheckAndCaculateTest {

    public static String check(String s) {
        if (s == null || s.length() == 0) {
            return null;
        }
        ArrayList<String> str = new ArrayList<String>();
        Arrays.stream(s.toString().split(" ")).forEach(new Consumer<String>() {
            @Override
            public void accept(String s) {
                if (!"".equals(s)) {
                    str.add(s); // 遍历去除""
                }
            }
        });
        if (null == str || 1 > str.size()) {
            return null;
        }
        //1.检验中缀表达式是否合法
        //1.1操作符"&&"，"||"，"="不能出现在首位，末位
        if ("&&".equals(str.get(0)) || "||".equals(str.get(0)) || "=".equals(str.get(0)) || "!=".equals(str.get(0))
                || "LIKE".equals(str.get(0)) || "LEFT_LIKE".equals(str.get(0)) || "RIGHT_LIKE".equals(str.get(0))
                || "IN".equals(str.get(0))) {
            return null;
        }
        //1.2操作符"&&"，"||"，"="不能连续,括号成对匹配
        LinkedList<String> stack = new LinkedList<>();
        for (int i = 0; i < str.size(); i++) {
            if ("(".equals(str.get(i))) {//左括号入栈
                stack.push(str.get(i));
            } else if (")".equals(str.get(i))) {//右括号出栈
                if (!("(".equals(stack.pop()))) {
                    return null;
                }
            } else if (("&&".equals(str.get(i)) || "||".equals(str.get(i)) || "=".equals(str.get(i)) || "!=".equals(str.get(i))
                    || "LIKE".equals(str.get(i)) || "LEFT_LIKE".equals(str.get(i)) || "RIGHT_LIKE".equals(str.get(i))
                    || "IN".equals(str.get(i)))
                    && ("&&".equals(str.get(i - 1)) || "||".equals(str.get(i - 1)) || "=".equals(str.get(i - 1)) || "!=".equals(str.get(i - 1))
                    || "LIKE".equals(str.get(i - 1)) || "LEFT_LIKE".equals(str.get(i - 1)) || "RIGHT_LIKE".equals(str.get(i - 1))
                    || "IN".equals(str.get(i - 1)))) {//连续操作符
                return null;
            }
        }
        return stack.isEmpty() ? String.join(" ", str) : null;//栈不为空说明括号不匹配
    }

    public static int priority(String c) {
        if ("=".equals(c) || "!=".equals(c) || "LIKE".equals(c) || "LEFT_LIKE".equals(c) || "RIGHT_LIKE".equals(c)
                || "IN".equals(c)) {
            return 3;
        } else if ("&&".equals(c)) {
            return 2;
        } else if ("||".equals(c)) {
            return 1;
        } else if ("(".equals(c)) {
            return 0;
        } else {
            throw new IllegalArgumentException("不合法的运算符:" + c);
        }
    }

    public static String infixToSuffix(String str) {
        String[] exp = str.split(" ");
        LinkedList<String> stack = new LinkedList<>();
        StringBuilder sb = new StringBuilder(exp.length);
        for (int i = 0; i < exp.length; i++) {
            String c = exp[i];
            if ("&&".equals(c) || "||".equals(c) || "=".equals(c) || "!=".equals(c) || "LIKE".equals(c)
                    || "RIGHT_LIKE".equals(c) || "LEFT_LIKE".equals(c) || "IN".equals(c)) {
                if (stack.isEmpty()) {
                    stack.push(c);
                } else {
                    if (priority(c) > priority(stack.peek())) {
                        stack.push(c);
                    } else {
                        while (!stack.isEmpty() && priority(stack.peek()) >= priority(c)) {
                            sb.append(stack.pop() + " ");
                        }
                        stack.push(c);
                    }
                }
            } else if ("(".equals(c)) {
                stack.push(c);
            } else if (")".equals(c)) {
                while (!stack.isEmpty() && !stack.peek().equals("(")) {
                    sb.append(stack.pop() + " ");
                }
                stack.pop();
            } else if (!"".equals(c)) {
                sb.append(c.replace("\"", "") + " ");
            }
        }
        while (!stack.isEmpty()) {
            sb.append(stack.pop());
        }
        return sb.toString();
    }

    public static boolean calculateSuffix(String suffix) {
        String[] s = suffix.split(" ");
        LinkedList<Object> stack = new LinkedList<>();
        for (int i = 0; i < s.length; i++) {
            if (("&&".equals(s[i])) || ("||".equals(s[i])) || ("=".equals(s[i])) || ("!=".equals(s[i]))
                    || ("LIKE".equals(s[i])) || ("LEFT_LIKE".equals(s[i])) || ("RIGHT_LIKE".equals(s[i]))
                    || ("IN".equals(s[i]))) {//操作符
                Object ob2 = stack.pop();
                Object ob1 = stack.pop();
                boolean result = false;
                if ("&&".equals(s[i])) {
                    result = ((boolean) ob1) && ((boolean) ob2);
                } else if ("||".equals(s[i])) {
                    result = ((boolean) ob1) || ((boolean) ob2);
                } else if ("=".equals(s[i])) {
                    result = ((String) ob1).equals((String) ob2);
                } else if ("!=".equals(s[i])) {
                    result = !((String) ob1).equals((String) ob2);
                } else if ("LIKE".equals(s[i])) {
                    result = !((String) ob1).contains((String) ob2);
                } else if ("LEFT_LIKE".equals(s[i])) {
                    result = ((String) ob1).startsWith((String) ob2);
                } else if ("RIGHT_LIKE".equals(s[i])) {
                    result = ((String) ob1).endsWith((String) ob2);
                } else if ("IN".equals(s[i])) {
                    result = ((String) ob2).contains((String) ob1);
                }
                stack.push(result);
            } else {//数字
                stack.push(trans(s[i]));
            }
        }
        return ((boolean) stack.pop());
    }

    private static String trans(String s) {
        if (s.equals("tranNo")) {
            return "300700";
        } else if (s.equals("channelNo")) {
            return "0202002";
        } else {
            return s;
        }
    }

    public static void main(String[] args) {

//        System.out.println(true || true && false); // true
//        System.out.println(false == true && false); // true

//        Scanner sc = new Scanner(System.in);
//        String str= sc.nextLine();
//        String str= "( src = 300700 && code = 0202002 ) || ( src = 300700 || code = 456789 )";
//        String str= " (  tranNo  = 300710  )  &&  (  channelNo  = 10101  )  ||  (  tranNo  RIGHT_LIKE 123  ) ";
        String str = " (  tranNo  = \"300710\"  )  &&  (  channelNo  = \"10101\"  )  ||  (  tranNo  RIGHT_LIKE \"123\"  ) ";
//        String str= " (  300700  = 300710  )  &&  (  10101  = 10101  )  ||  (  tranNo  RIGHT_LIKE 123  ) ";
        System.out.print("中缀表达式：");
        String infix = check(str);
        if (infix == null) {
            System.out.println("表达式不合法");
        } else {
            System.out.println(infix);
            String suffix = infixToSuffix(infix);
            System.out.println("后缀表达式：" + suffix);
            System.out.println("计算结果：" + calculateSuffix(suffix));
        }
    }
}
